from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By


class BaseMethod:
    """
    浏览器的基本操作方法
    """

    def __init__(self, driver):
        self.driver = driver
        self.actions = ActionChains(driver)

    def get_element(self, method, value):
        """
        获取等待出现后的元素
        Args:
            method: 定位方法
            value: 定位元素的值
        Returns:
            webelement类型的元素对象
        """
        msg = '("{}", "{}") 无法使用给定的搜索参数在页面上找到'.format(method, value)
        if method == 'id':
            locator = (By.ID, value)
        elif method == 'xpath':
            locator = (By.XPATH, value)
        elif method == 'css':
            locator = (By.CSS_SELECTOR, value)
        elif method == 'name':
            locator = (By.NAME, value)
        elif method == 'class_name':
            locator = (By.CLASS_NAME, value)
        elif method == 'link_text':
            locator = (By.LINK_TEXT, value)
        elif method == 'part_link_text':
            locator = (By.PARTIAL_LINK_TEXT, value)
        else:
            raise Exception('无效的定位方法')
        return WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located(locator), msg)

    def get_elements(self, method, value):
        """
        获取符合条件的所有元素
        Args:
            method: 定位方法
            value: 定位元素的值
        Returns:
            webelement类型的元素列表
        """
        if method == 'id':
            locator = (By.ID, value)
        elif method == 'xpath':
            locator = (By.XPATH, value)
        elif method == 'css':
            locator = (By.CSS_SELECTOR, value)
        elif method == 'name':
            locator = (By.NAME, value)
        elif method == 'class_name':
            locator = (By.CLASS_NAME, value)
        elif method == 'link_text':
            locator = (By.LINK_TEXT, value)
        elif method == 'part_link_text':
            locator = (By.PARTIAL_LINK_TEXT, value)
        else:
            raise Exception('无效的定位方法')
        return self.driver.find_elements(*locator)

    def send_keys(self, *args):
        """
        元素输入值
        Args:
            *args: 接受三个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值，第三个必须是输入的文本内容
        """
        self.get_element(args[0], args[1]).send_keys(args[2])

    def click(self, *args):
        """
        点击元素
        Args:
            *args: 接受两个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值
        """
        self.get_element(*args).click()

    def get_text(self, *args):
        """
        获取元素的文本值
        Args:
            *args: 接受两个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值
        """
        return self.get_element(*args).text

    def left_click(self, *args):
        """
        模拟鼠标左键单击元素
        Args:
            *args: 接受两个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值
        """
        self.actions.move_to_element(self.get_element(*args))
        self.actions.click(self.get_element(*args))
        self.actions.perform()

    def keyboard_input(self, *args):
        """
        模拟键盘输入。
        如果传入三个参数，则向指定元素输入值；
        如果仅传一个参数，则向当前焦点元素输入值。
        Args:
            *args: 接受三个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值，第三个必须是输入的文本内容
        """
        if len(args) == 1:
            self.actions.send_keys(args[0])
        else:
            self.actions.send_keys_to_element(self.get_element(args[0], args[1]), args[2])
        self.actions.perform()

    def clear(self, *args):
        """
        清空文本内容
        Args:
            *args: 接受两个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值
        """
        self.get_element(*args).send_keys(Keys.CONTROL, 'a')
        self.actions.send_keys(Keys.BACKSPACE)
        self.actions.perform()

    def get_attribute(self, *args):
        """
        获取节点元素的属性值
        Args:
            *args: 接受三个参数的传入，且第一个必须是元素定位方法，第二个必须是元素定位值，第三个必须是属性
        """
        return self.get_element(args[0], args[1]).get_attribute(args[2])

    def drag_and_drop(self, source, target):
        """
        将源元素拖动到目标元素的位置
        Args:
            source: 源元素
            target: 目标元素
        """
        self.actions.drag_and_drop(source, target)
        self.actions.perform()

    def page_refresh(self):
        """
        页面刷新
        """
        self.driver.refresh()

    def switch_tab_page(self, index):
        """
        切换浏览器标签页
        Args:
            index: 窗口句柄的索引
        """
        self.driver.switch_to.window(self.driver.window_handles[index])
